package vali

import (
	"egin/pkg/database"
	"egin/pkg/gi18n"
	"reflect"
	"regexp"
	"strings"
	"sync"

	"github.com/gin-gonic/gin/binding"

	"github.com/go-playground/validator/v10"
)

var Val *validator.Validate
var valOnce sync.Once

func init() {

	v, ok := binding.Validator.Engine().(*validator.Validate)
	if ok {
		Val = v
		unique()
	}
}

//封装一个通用的正则方法
func Regex(tag, pattern string) {

	Val.RegisterValidation(tag, func(fl validator.FieldLevel) bool {
		if val, ok := fl.Field().Interface().(string); ok {
			if matched, _ := regexp.MatchString(pattern, val); matched {
				return true
			}
		}
		return false

	})
}

//unique=#模型名称 字段 id(唯一表示 更新需要，新增不要)
func unique() {

	Val.RegisterValidation("unique", func(fl validator.FieldLevel) bool {

		if val, ok := fl.Field().Interface().(string); ok {

			param := strings.Fields(fl.Param())
			len := len(param)
			var count int64
			if len >= 3 { //更新
				err := database.Db().Table(param[0]).Where(param[1]+" = ?", val).Where(param[2]+" <> ?", fl.Top().FieldByName(param[2]).Interface()).Count(&count).Error
				if err == nil {
					if count == 0 {
						return true
					}
				}
				return false
			} else { //新增
				err := database.Db().Table(param[0]).Where(param[1]+" = ?", val).Count(&count).Error
				if err == nil {
					if count == 0 {
						return true
					}
				}
				return false
			}

		}
		return false

	})
}

func ValidErrMsg(obj interface{}, err error) string {
	getObj := reflect.TypeOf(obj) //获取tag要用TypeOf

	if err != nil {
		if errs, ok := err.(validator.ValidationErrors); ok {
			for _, e := range errs {
				if f, exist := getObj.Elem().FieldByName(e.Field()); exist {
					if value, ok := f.Tag.Lookup(e.Tag() + "-msg"); ok {
						if strings.HasPrefix(value, "_") && strings.HasSuffix(value, "_") {
							return gi18n.Lang(value)
						} else {
							return string(value)
						}

					} else {
						if value, ok = f.Tag.Lookup("label"); ok {

							if strings.HasPrefix(value, "_") && strings.HasSuffix(value, "_") {

								return gi18n.LangT(e.Tag(), map[string]string{"Field": gi18n.Lang(value), "Param": e.Param()})

							} else {

								return gi18n.LangT(e.Tag(), map[string]string{"Field": value, "Param": e.Param()})
							}

						} else if value, ok = f.Tag.Lookup("json"); ok {

							return gi18n.LangT(e.Tag(), map[string]string{"Field": value, "Param": e.Param()})

						} else if value, ok = f.Tag.Lookup("form"); ok {

							return gi18n.LangT(e.Tag(), map[string]string{"Field": value, "Param": e.Param()})

						}

					}
				}
			}
		}
	}
	return ""
}
